package com.waimai1.waimai.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.waimai1.waimai.common.Utils;
import com.waimai1.waimai.entity.HwOrder;
import com.waimai1.waimai.entity.MyOrder;
import com.waimai1.waimai.entity.WepayOrder;
import com.waimai1.waimai.exception.EnumException;
import com.waimai1.waimai.exception.NotErrorException;
import com.waimai1.waimai.service.HwOrderService;
import com.waimai1.waimai.service.HwService;
import com.waimai1.waimai.service.MyOrderService;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

//获取hw数据的基础服务类
@Service
@Slf4j
public class HwServiceImpl implements HwService {
    @Autowired
    public RedisTemplate redisTemplate;
    @Autowired
    public MyOrderService orderService;
    @Autowired
    public HwOrderService hwOrderService;
    @Value("${Hw.userNo}")
    private String userNo;
    @Value("${Hw.key}")
    private String key;
    @Value("${Hw.notifyUrl}")
    private String notifyUrl;
    @Override
    public  String getHwSign(TreeMap<String, Object> argsMap, String url)  {
        String flag="movie";
        if(url.contains("jfshou.cn/api")){
            flag="pinpai";
        }
        return  Utils.getHwSign(argsMap, key,flag);
    }
    @Override
    public Object getHwData(TreeMap<String, Object> argsMap,String sign, String url)  {
        argsMap.put("sign", sign);
        return Utils.getHwData(argsMap,url);
    }
    @Override
    public ArrayList<Object>[] getFilmService() throws UnsupportedEncodingException {
        String time = String.valueOf(new Date().getTime());
        TreeMap<String, Object> argsMap = Utils.getParams("userNo", userNo, "timestamp", time);
        String sign= getHwSign(argsMap, Utils.HW_MOVIE_FILM);
        Map<String, Object> res = (Map<String, Object>) getHwData(argsMap,sign, Utils.HW_MOVIE_FILM);
        if (res.get("code").equals(200)) {
//            排序
            ArrayList<HashMap> sortList = (ArrayList<HashMap>) res.get("data");
            ArrayList<HashMap> hotList = new ArrayList<>();
            ArrayList<HashMap> waitList = new ArrayList<>();
            //取时间最近的影片
            Map<String, String> movieAndId = new HashMap<>();
//            Map<String, String> movieImgAndId = new HashMap<>();
            for (HashMap<String, Object> item : sortList) {
                //把影片列表
                if (item.get("publishStatus").equals("HOT")) {
                        hotList.add(item);
                } else if (item.get("publishStatus").equals("WAIT")) {
                        waitList.add(item);
                }
                movieAndId.put(item.get("movieId").toString(),(String) item.get("movieName"));
            }
            ArrayList[] responseData = {hotList, waitList};
            String resData= JSON.toJSONString(responseData);
            redisTemplate.opsForValue().set("movieList",resData);
            redisTemplate.expire("movieList",300, TimeUnit.SECONDS);
            redisTemplate.opsForHash().putAll("movieAndId",movieAndId);
            redisTemplate.expire("movieAndId",300, TimeUnit.SECONDS);
//            redisTemplate.opsForHash().putAll("movieImgAndId",movieAndId);
//            redisTemplate.expire("movieImgAndId",300, TimeUnit.SECONDS);
            return responseData;
        }
        throw new NotErrorException((Integer) res.get("code"),res.get("message").toString());
    }
//    创建电影订单
    public void createOrder(String orderNo){
        String time = String.valueOf(new Date().getTime());
        TreeMap<String,Object> argsMap=Utils.getParams("userNo",userNo,"orderNo",orderNo,"timestamp",time);
        String sign=getHwSign(argsMap,Utils.HW_MOVIE_CREAT_ORDER);
        Map<String,Object> res= (Map<String,Object>)getHwData(argsMap,sign,Utils.HW_MOVIE_CREAT_ORDER);
        LambdaQueryWrapper<MyOrder> orderLambdaQueryWrapper =new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(MyOrder::getHwOrderId,orderNo);
        MyOrder order=orderService.getOne(orderLambdaQueryWrapper,false);
        order.setHwStatus(res.get("code").toString()+"-"+res.get("message"));
        Integer[] errCodes={9001,9005,9006,9007,9009,9021};
        if(res.get("code").equals(200)){
            order.setStatus(Utils.STATUS_OVER);
        }else if(Arrays.asList(errCodes).contains(res.get("code"))){
            order.setStatus(Utils.STATUS_WAIT_REFUND);

        }
        boolean updateRes=orderService.updateById(order);
        if(!updateRes){
            log.error("更新订单表失败");
        }
    }
    //创建品牌订单
    public void createOrder(Integer brandId,String restaurantId,String takePhone,String eatType,String productsJson,String outTradeNo) throws UnsupportedEncodingException {

    String time = String.valueOf(new Date().getTime());
        String notify=notifyUrl;
        TreeMap<String,Object> argsMap= Utils.getParams("user_no",userNo,"brand_id",brandId,"restaurant_id",restaurantId,"phone_number",takePhone,"eat_type",eatType,"products",productsJson,"notify_url",notify,"trade_no",outTradeNo,"timestamp",time);
//      先计算签名再对products编码
        String sign=getHwSign(argsMap,Utils.HW_PINPAI_CREAT_ORDER);
        argsMap.put("products", URLEncoder.encode(productsJson, "UTF-8"));
        Map<String,Object> res=(Map<String,Object>) getHwData(argsMap,sign,Utils.HW_PINPAI_CREAT_ORDER);
        //更新订单表
        LambdaQueryWrapper<MyOrder> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(MyOrder::getOutTradeNo,outTradeNo);
        MyOrder order=orderService.getOne(queryWrapper,false);
        Map<String,String> resData=(Map<String,String>) res.get("data");
        order.setHwStatus(res.get("error_code").toString()+"-"+res.get("error_msg"));
        order.setHwOrderId(resData.get("order_no"));
        Integer[] errCodes={204,9001,9005,9006,9007,9009};
        if(res.get("error_code").equals(200)){
            order.setStatus(Utils.STATUS_OVER);
        }else if(Arrays.asList(errCodes).contains(res.get("error_code"))){
            order.setStatus(Utils.STATUS_WAIT_REFUND);
        }
        boolean updateRes=orderService.updateById(order);
        if(!updateRes){
            log.error("更新订单表失败");
        }
    }
    //电影search
    public void searchOrder(String tradeNo) throws NoSuchFieldException, InstantiationException, IllegalAccessException, JsonProcessingException, ParseException {
            String time = String.valueOf(new Date().getTime());
            TreeMap<String,Object> argsMap=Utils.getParams("userNo",userNo,"tradeNo",tradeNo,"timestamp",time);
            String sign=getHwSign(argsMap,Utils.HW_MOVIE_SEARCH_ORDER);
            Map<String,Object> res= (Map<String,Object>)getHwData(argsMap,sign,Utils.HW_MOVIE_SEARCH_ORDER);
            log.info("searchhw"+JSONUtils.toJSONString(res));
            if(!res.get("code").equals(200)){
                throw new NotErrorException(EnumException.NO_CREATE_HW_ORDER);
            }
            hwNotify((Map<String,Object>)res.get("data"));
    }
//    品牌search
    public void searchOrder(String tradeNo,Integer brand_id) throws JsonProcessingException, IllegalAccessException, NoSuchFieldException, InstantiationException, ParseException {
        String time = String.valueOf(new Date().getTime());
        TreeMap<String,Object> argsMap=Utils.getParams("user_no",userNo,"brand_id",brand_id,"trade_no",tradeNo,"timestamp",time);
        String sign=getHwSign(argsMap,Utils.HW_PINPAI_SEARCH_ORDER);
        Map<String,Object> res= (Map<String,Object>)getHwData(argsMap,sign,Utils.HW_PINPAI_SEARCH_ORDER);
        if(!res.get("code").equals(200)){
            throw new NotErrorException(EnumException.NO_CREATE_HW_ORDER);
        }
        hwNotify((Map<String,Object>)res.get("data"));
    }
    public String hwNotify(Map<String,Object> map) throws JsonProcessingException, IllegalAccessException, NoSuchFieldException, InstantiationException, ParseException {
        log.info("hwnotify:"+JSONUtils.toJSONString(map));
        //电影
        if(map.containsKey("tradeNo")) {
            LambdaQueryWrapper<HwOrder> hwqueryWrapper = new LambdaQueryWrapper();
            hwqueryWrapper.eq(HwOrder::getTradeNo, map.get("tradeNo"));
            //如果存在就返回
            if(null!=hwOrderService.getOne(hwqueryWrapper)){
                return "OK";
            };
            String orderstatus = (String) map.get("orderStatus");
            LambdaQueryWrapper<MyOrder> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(MyOrder::getOutTradeNo, map.get("tradeNo"));
            MyOrder order = new MyOrder();
            order.setOutTradeNo((String) map.get("tradeNo"));
            order.setHwStatus(orderstatus);
            HwOrder hworder=Utils.mapToEntity(map,HwOrder.class);
            hworder.setHwOrderNo((String) map.get("orderNo"));
            hworder.setOrderTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String) map.get("orderTime")));
            hworder.setOrderStatus((String) map.get("orderStatus"));
            hworder.setBrandName((String) map.get("movieName"));
            if ("GENERATE_SUCCESS".equals(orderstatus)) {
                String ticketCode = JSONUtils.toJSONString(map.get("ticketCode"));
                order.setStatus(Utils.STATUS_OVER);
                order.setTicketCode(ticketCode);
                hworder.setCode(ticketCode);
                orderService.update(order, queryWrapper);
//                创建hw订单
                if(!hwOrderService.save(hworder)){
                    log.error("创建hw表单失败");
                    return null;
                };
            } else if ("CLOSE".equals(orderstatus)) {
                //进行微信退款
              order.setStatus(Utils.STATUS_WAIT_REFUND);
              if(!orderService.update(order,queryWrapper)){
                  log.error("hw下单失败，更新订单表状态失败");
                  return null;
              };
//                创建hw订单
                if(!hwOrderService.save(hworder)){
                    log.error("创建hw表单失败");
                    return null;
                };
            }
        }else if(map.containsKey("trade_no")){//        品牌
            LambdaQueryWrapper<HwOrder> hwqueryWrapper = new LambdaQueryWrapper();
            hwqueryWrapper.eq(HwOrder::getTradeNo, map.get("trade_no"));
            if(null!=hwOrderService.getOne(hwqueryWrapper)){
                return "OK";
            };
            //校验sign是否匹配
            TreeMap<String,Object> argsMap=Utils.getParams("brand_id",map.get("brand_id"),"brand_name",map.get("brand_name"),"order_no",map.get("order_no"),"trade_no",map.get("trade_no"),"order_status",map.get("order_status"),"code",map.get("code"),"timestamp",map.get("timestamp"));
//            code只在成功时返回
            if(null==argsMap.get("code")){
                argsMap.remove("code");
            }
            String sign=getHwSign(argsMap,Utils.HW_PINPAI_SEARCH_ORDER);
            if(!sign.equals(map.get("sign"))){
                log.error("hw通知校验错误");
                return null;
            }
            LambdaQueryWrapper<MyOrder> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(MyOrder::getOutTradeNo, map.get("trade_no"));
            MyOrder order = new MyOrder();
            order.setOutTradeNo((String) map.get("trade_no"));
            order.setHwOrderId((String)map.get("order_no"));
            //创建hw订单
            HwOrder hwOrder=new HwOrder();
            hwOrder.setBrandId((Integer) map.get("brand_id"));
            hwOrder.setBrandName((String)map.get("brand_name"));
            hwOrder.setHwOrderNo((String)map.get("order_no"));
            hwOrder.setOrderStatus((String)map.get("order_status"));
            hwOrder.setTradeNo((String)map.get("trade_no"));
            hwOrder.setOrderTime(new Date (Long.parseLong((String)map.get("timestamp"))));
            if("OUT_MEAL".equals(map.get("order_status"))){
                order.setTicketCode((String) map.get("code"));
                order.setStatus(Utils.STATUS_OVER);
                order.setHwStatus("出餐成功");
                if(map.get("brand_id").equals(2)||map.get("brand_id").equals(13)){
                    order.setQrCode(JSONUtils.toJSONString(map.get("qr_codes")));
                }
                if(!orderService.update(order,queryWrapper)){
                    log.error("出餐成功更新订单表失败");
                    return null;
                };
                hwOrder.setCode((String)map.get("code"));
                if(!hwOrderService.save(hwOrder)){
                    log.error("出餐成功hw订单表失败");
                    return null;
                };
            }else if("OUT_MEAL_PART".equals(map.get("order_status"))){
                order.setTicketCode((String) map.get("code"));
                order.setStatus(Utils.STATUS_WAIT_REFUND);
                order.setHwStatus("部分出餐");
                if(map.get("brand_id").equals(2)||map.get("brand_id").equals(13)){
                    order.setQrCode(JSONUtils.toJSONString(map.get("qr_codes")));
                }
                if(!orderService.update(order,queryWrapper)){
                    log.error("部分出餐更新订单表失败");
                    return null;
                };
                hwOrder.setCode((String)map.get("code"));
                hwOrder.setPartialRefundPrice((String)map.get("partial_refund_price"));
                hwOrder.setPartialRefundProduct( JSONUtils.toJSONString(map.get("partial_refund_product")));
                if(!hwOrderService.save(hwOrder)){
                    log.error("部分出餐hw订单表失败");
                    return null;
                };
            }
            else if("FAIL".equals(map.get("order_status"))){
                order.setStatus(Utils.STATUS_WAIT_REFUND);
                order.setHwStatus("出餐失败");
                if(!orderService.update(order,queryWrapper)){
                    log.error("出餐失败更新订单表失败");
                    return null;
                };
                if(!hwOrderService.save(hwOrder)){
                    log.error("出餐失败hw订单表失败");
                    return null;
                };
            }
        }
        return "OK";
    }
}
